Skip to content
Pasqal Documentation

Tutorial 5 - Using a Quantum Device to solve Weighted MIS

We wish to install two Python libraries called mygreatlib and anotherlib. However, there are conflicts between these Python libraries and some versions of Python, so we need to also pick the most modern version of Python that is compatible with both libraries.

import math
import networkx as nx
PYTHON_VERSIONS = ["Python 3.8", "Python 3.9", "Python 3.10", "Python 3.11", "Python 3.12", "Python 3.13"]
COMPATIBILITY_MY_GREAT_LIB = ["Python 3.9", "Python 3.11", "Python 3.13"]
COMPATIBILITY_ANOTHER_LIB = ["Python 3.10", "Python 3.11", "Python 3.12", "Python 3.13"]
# Define our graph.
graph = nx.Graph()
# Each node represents something we may install:
# - the libraries
graph.add_nodes_from(["mygreatlib", "anotherlib"])
# - Python
graph.add_nodes_from(PYTHON_VERSIONS)
# One may only install one version of Python at a time
for (i, version) in enumerate(PYTHON_VERSIONS):
for other_version in PYTHON_VERSIONS[i+1:]:
graph.add_edge(version, other_version)
# Our libraries are only compatible with some versions of Python
for version in PYTHON_VERSIONS:
if version not in COMPATIBILITY_MY_GREAT_LIB:
graph.add_edge("mygreatlib", version)
if version not in COMPATIBILITY_ANOTHER_LIB:
graph.add_edge("anotherlib", version)
# We'd like the most recent version of Python that matches all criteria,
# so let's give a higher priority to more recent versions of Python.
#
# We do this by setting attribute `weight` of the node.
for (i, version) in enumerate(PYTHON_VERSIONS):
graph.nodes[version]["weight"] = 1 + math.log(i + 1)
# Nodes that do not have an explicit weight are impliclitly set to `1.0`.
from mis import MISInstance
instance = MISInstance(graph)
instance.draw()

We use the same solver as in tutorial 1.

The only difference is that we pass weighting = Weighting.WEIGHTED to instruct the solver to solve the Weighted MIS problem, by opposition to the regular MIS problem.

from mis import BackendConfig, BackendType, SolverConfig, Weighting, MISSolver
solver_config = SolverConfig(
# Use the QuTIP backend.
backend = BackendConfig(
backend = BackendType.QUTIP
),
# Instruct the solver to use the weights
weighting = Weighting.WEIGHTED,
# Perform up to 10 quantum measures.
max_iterations=10
)
# Run the solver
solver = MISSolver(instance, solver_config)
solutions = solver.solve()
# Display results
print("MIS solution:", solutions[0].nodes)
print("Solution frequency:", solutions[0].frequency)
print("Solution size:", solutions[0].size)
solutions[0].draw()

Formally, the difference between MIS and wMIS is that MIS maximizes the number of nodes in the solution, while wMIS maximizes the total weight of nodes in the solution, where each node has a weight of 1.0 if no weight is specified.

This means that wMIS can return a solution that is smaller (in number of nodes) than MIS.

For instance, we could de-prioritize anotherlib by giving it a weight < 0.

graph.nodes["anotherlib"]["weight"] = -1.0
instance = MISInstance(graph)
# Run the solver
solver = MISSolver(instance, solver_config)
solutions = solver.solve()
# Display results
print("MIS solution:", solutions[0].nodes)
print("Solution frequency:", solutions[0].frequency)
print("Solution size:", solutions[0].size)
solutions[0].draw()
graph.nodes["anotherlib"]["weight"] = 1.0 # Restore `anotherlib` to its default priority.
graph.nodes["Python 3.8"]["weight"] = 100
instance = MISInstance(graph)
# Run the solver
solver = MISSolver(instance, solver_config)
solutions = solver.solve()
# Display results
print("MIS solution:", solutions[0].nodes)
print("Solution frequency:", solutions[0].frequency)
print("Solution size:", solutions[0].size)
solutions[0].draw()

If you're interested in understanding how things work behind the hood, we have written up an in-depth tutorial on how to manipulate cold atoms and laser pulses to solve this problem: https://pulser.readthedocs.io/en/stable/tutorials/mwis.html (external)